﻿using Bentley.DgnPlatformNET.DgnEC;
using Bentley.DgnPlatformNET;
using Bentley.ECObjects.Instance;
using Bentley.GeometryNET;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Bentley.DgnPlatformNET.Elements;
using static Bentley.DgnPlatformNET.CustomProperty;
using Bentley.MstnPlatformNET;

namespace CheccCoverplateCulvertAssemble.Operation.HXD
{
    internal class BodyProperty
    {   
        //八字墙
        public static void attachDataBlockToCubeAliform(Element cube,Element cubeBasics, string wallLong, string wallHigh, string topWidth, string bottomWidth, string fileldAngle, string wallSpaceSlope,string backDrainSlope,string aliformBasicsInside,string aliformBasicsOutside,string aliformBasicsThickness, string solidName)
        {
            //墙长
            string Txt = "wallLong," + wallLong;
            //墙高
            Txt += "\r\n" + "wallHigh," + wallHigh;
            //顶宽
            Txt += "\r\n" + "topWidth," + topWidth;
            //底宽
            Txt += "\r\n" + "bottomWidth," + bottomWidth;
            //张角
            Txt += "\r\n" + "fileldAngle," + fileldAngle;
            //墙面坡率
            Txt += "\r\n" + "wallSpaceSlope," + wallSpaceSlope;
            //墙背坡率
            Txt += "\r\n" + "backDrainSlope," + backDrainSlope;
            //翼墙基础内侧襟边
            Txt += "\r\n" + "aliformBasicsInside," + aliformBasicsInside;
            //翼墙基础外侧襟边
            Txt += "\r\n" + "aliformBasicsOutside," + aliformBasicsOutside;
            //翼墙基础厚度
            Txt += "\r\n" + "aliformBasicsThickness," + aliformBasicsThickness;
            //八字墙体积
            Txt += "\r\n" + "aliformVolume," + SolidHelper.getVolume(cube);
            //八字墙基础体积
            Txt += "\r\n" + "aliformBasicsVolume," + SolidHelper.getVolume(cubeBasics);
            SolidHelper.SetDatablock(20211, ref cube, Txt);
            //ToRebar(cube, solidName+"_八字墙_构造体", "八字墙", solidName);
        }

        //截水墙
        public static void attachDataBlockToCubePave(Element cube, string cutoffWallLong, string cutoffWallHigh, string cutoffWallWide, string solidName)
        {
            //墙长
            string Txt = "cutoffWallLong," + cutoffWallLong;
            //墙高
            Txt += "\r\n" + "cutoffWallHigh," + cutoffWallHigh;
            //墙宽
            Txt += "\r\n" + "cutoffWallWide," + cutoffWallWide;
            //体积
            Txt += "\r\n" + "cutoffWallVolume," + SolidHelper.getVolume(cube);
            SolidHelper.SetDatablock(20211, ref cube, Txt);
            //ToRebar(cube, solidName+"_截水墙_构造体", "截水墙", solidName);
        }

        //铺砌
        public static void attachDataBlockToCubeCutoffWall(Element cube, string thickness,string solidName)
        {
            //厚度
            string Txt = "thickness," + thickness;
            //体积
            Txt += "\r\n" + "Volume," + SolidHelper.getVolume(cube);
            SolidHelper.SetDatablock(20211, ref cube, Txt);
           // ToRebar(cube, solidName+"_铺砌_构造体", "铺砌", solidName);
        }

        private static List<(string standardName, string standValue)> tuples = new List<(string standardName, string standValue)>();

        public static void ToRebar(Element rebarEle, string fileName, string bodyName,string solidName)
        {
            //读取钢筋datablock数据
            string txt = SolidHelper.GetDatablock(20211, ref rebarEle);
            List<string> list = SolidHelper.StringSplit(txt, "\r\n");
            tuples.Clear();
            foreach (string s in list)
            {
                if (s.Contains(","))
                    tuples.Add((s.Split(',')[0], s.Split(',')[1]));
            }
            switch (solidName)
            {
                case "盖板涵":
                    solidName = "SlabCulvertFiles";
                    break;
                case "箱涵":
                    solidName = "BoxCulvertFiles";
                    break;
                case "圆管涵":
                    solidName = "CircularCulvertFiles";
                    break;
                default:
                    break;
            }
            //获取属性文件路径
            string[] strings = { solidName };
            string propertyFileDir = JsonConvert.DeserializeObject<string[]>(SolidHelper.GetINIvalue(strings, ""))[0];
            //属性文件路径
            string path = SolidHelper.WorkSpacePath + propertyFileDir.Substring(1) + "\\" + fileName + ".csv";
            //读取属性文件
            if (path != "")
                attachPropertyToEle(path, rebarEle, bodyName);
        }

        private static void attachPropertyToEle(string path, Element ele, string bodyName)
        {
            /*
             * 属性名称,计算基准,计算公式或值
               模型元素名称,name,="圆管涵正管节"+ name 
               分类编码,,36-15.03.00.00
               直径,rebarDiameter,=rebarDiameter
               体积,rebarVolume,=rebarVolume
               截面类型,,带肋(46-05.54.03.00)
               钢筋等级,,HRB400(36-15.03.00.00)
               钢筋重量,,=rebarVolume*7.86*1000
               钢筋长度,rebarLength,=rebarLength
             */
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
            StreamReader file = new StreamReader(fs, Encoding.Default);
            string txt = file.ReadLine();
            Dictionary<string, string> dict = new Dictionary<string, string>();
            while ((txt = file.ReadLine()) != null)
            {
                string[] strings = txt.Split(',');
                dict.Add(strings[0], CalExpressionValue(strings[2], tuples));
            }
            file.Close();
            foreach (var item in dict)
            {
                AttachItemToElement(ele, "涵洞", bodyName, item.Key, TypeKind.String, item.Value);
            }
        }

        //计算表达式的值  expression 如果是数学表达式 第一个字符是=
        private static string CalExpressionValue(string expression, List<(string standardName, string standValue)> tuples)
        {
            if (expression.Contains("="))
            {
                var matchs = Regex.Split(expression.Substring(1), @"\(|\)|\+|\-|\*|\/").Where(s => s != "");
                foreach (var item in matchs)
                {
                    var obj = tuples.FirstOrDefault(p => p.standardName.ToLower() == item.ToLower());
                    if ((null, null) == obj)
                    {
                        continue;
                    }
                    expression = expression.Replace(item, null == obj.standValue ? "" : obj.standValue);
                }
                try
                {
                    string formula = expression.Substring(1);
                    DataTable dt = new DataTable();
                    string really_data = dt.Compute(formula, "false").ToString();
                    double calData = Math.Round(Convert.ToDouble(really_data), 6);
                    return calData.ToString();
                }
                catch
                {
                    string[] strings = expression.Substring(1).Split('+');
                    string really_data = "";
                    if (strings.Count() > 0)
                    {
                        foreach (var item in strings)
                        {
                            really_data += item;
                        }
                    }
                    return really_data;
                }
            }
            else
                return expression;
        }

        //将属性赋值给元素, 参数: 元素ID, 库名, 组名, 属性显示名, 属性类型, 属性值
        public static void AttachItemToElement(Element ele, string itemLibName, string itemTypeName, string propertyName, TypeKind propertyType, object propertyValue)
        {
            DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
            CustomItemHost host = new CustomItemHost(ele, true);

            ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);
            if (null == itemTypeLibrary)
            {
                itemTypeLibrary = ItemTypeLibrary.Create(itemLibName, dgnFile);
            }
            ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);
            if (itemType == null)
            {
                itemType = itemTypeLibrary.AddItemType(itemTypeName);
            }
            IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);
            if (item == null)
            {
                item = host.ApplyCustomItem(itemType, true);
            }
            CustomProperty property = itemType.GetPropertyByName(propertyName);
            if (property == null)
            {
                CustomProperty Cp = itemType.AddProperty(propertyName);
                Cp.Type = propertyType;
                switch (Cp.Type)
                {
                    case TypeKind.Boolean:
                        Cp.DefaultValue = (bool)propertyValue;
                        break;
                    case TypeKind.String:
                        Cp.DefaultValue = (string)propertyValue;
                        break;
                    case TypeKind.DateTime:
                        Cp.DefaultValue = (DateTime)propertyValue;
                        break;
                    case TypeKind.Double:
                        Cp.DefaultValue = (double)propertyValue;
                        break;
                    case TypeKind.Integer:
                        Cp.DefaultValue = (int)propertyValue;
                        break;
                    case TypeKind.Point:
                        Cp.DefaultValue = (DPoint3d)propertyValue;
                        break;
                }
            }
            else
            {
                string internalName = property.InternalName;
                IECPropertyValue val = item.GetPropertyValue(internalName);

                switch (propertyType)
                {
                    case TypeKind.Boolean:
                        item.SetValue(internalName, (bool)propertyValue);
                        break;
                    case TypeKind.String:
                        item.SetValue(internalName, (string)propertyValue);
                        break;
                    case TypeKind.DateTime:
                        item.SetValue(internalName, (DateTime)propertyValue);
                        break;
                    case TypeKind.Double:
                        item.SetValue(internalName, (double)propertyValue);
                        break;
                    case TypeKind.Integer:
                        item.SetValue(internalName, (int)propertyValue);
                        break;
                    case TypeKind.Point:
                        item.SetValue(internalName, (DPoint3d)propertyValue);
                        break;
                }
            }
            itemTypeLibrary.Write();
            if (item != null) item.ScheduleChanges(ele);
            ele.ReplaceInModel(ele);
        }
    }
}
